package whf.framework.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 设置一个过期期限，这样以后的操作中将会忽略过期对象
 * @author wanghaifeng
 *
 */
public class ExpireableMap<K,V> implements Map<K,V> {
	private Map<K, ExpireableObject> cachedMap ;
	
	private boolean expireable;
	
	private long expireTime;
	
	public ExpireableMap(){
		this.cachedMap = new HashMap<K, ExpireableObject>(10);
	}
	
	public ExpireableMap(long expire){
		this();
		this.expireTime = expire;
		if(this.expireTime > 0){
			this.expireable = true;
		}
	}
	
	public ExpireableMap(int initialCapacity){
		this.cachedMap = new HashMap<K, ExpireableObject>(initialCapacity);
	}
	
	public void clear() {
		this.cachedMap.clear();
	}

	public boolean containsKey(Object key) {
		this.removeExpiredObjects();
		return this.cachedMap.containsKey(key);
	}

	public boolean containsValue(Object value) {
		for(ExpireableObject obj: this.cachedMap.values()){
			if(obj.equals(value)){
				if(obj.isExpired()){
					return false;
				}else{
					return true;
				}
			}
		}
		return false;
	}

	public Set<Entry<K,V>> entrySet() {
//		this.removeExpiredObjects();
//		return this.cachedMap.entrySet();
		throw new RuntimeException("Not implements!");
	}

	public V get(Object key) {
		ExpireableObject co = this.cachedMap.get(key);
		if(co == null) return null;
		if(co.isExpired()){
			this.remove(key);
			return null;
		}
		return co.cachedObject;
	}

	public boolean isEmpty() {
		this.removeExpiredObjects();
		return this.cachedMap.isEmpty();
	}

	public Set<K> keySet() {
		this.removeExpiredObjects();
		return this.cachedMap.keySet();
	}

	public V put(K key, V value) {
		this.cachedMap.put(key, new ExpireableObject(value));
		return value;
	}

	public void putAll(Map<? extends K, ? extends V> t) {
		if(t == null) return;
		for(K key: t.keySet()){
			this.put(key, t.get(key));
		}
	}

	public V remove(Object key) {
		ExpireableObject co = this.cachedMap.get(key);
		this.cachedMap.remove(key);
		return co.cachedObject;
	}

	public int size() {
		this.removeExpiredObjects();
		return this.cachedMap.size();
	}

	public Collection<V> values() {
		this.removeExpiredObjects();
		List<V> list = new ArrayList<V>();
		for(ExpireableObject co: this.cachedMap.values()){
			list.add(co.cachedObject);
		}
		return list;
	}
	
	public void removeExpiredObjects(){
		if(this.expireable){
			for(Iterator keys = this.cachedMap.keySet().iterator();keys.hasNext();){
				Object key = keys.next();
				ExpireableObject co = this.cachedMap.get(key);
				if(co.isExpired()){
					this.cachedMap.remove(key);
				}
			}
		}
	}
	
	class ExpireableObject{
		private V cachedObject;
		
		private long cacheTime;
		
		ExpireableObject(V obj){
			this.cachedObject = obj;
			this.cacheTime = System.currentTimeMillis();
		}
		
		boolean isExpired(){
			return expireable && System.currentTimeMillis() - cacheTime > expireTime;
		}
	}
	
	class ExpireableEntry implements Entry<K,V>{
		private K key;
		
		private V value;
		
		private long cacheTime;

		ExpireableEntry(Entry<K,V> entry){
			this.key = entry.getKey();
			this.value = entry.getValue();
			this.cacheTime = System.currentTimeMillis();
		}
		
		public K getKey() {
			return key;
		}

		public void setKey(K key) {
			this.key = key;
		}

		public V getValue() {
			return value;
		}

		public V setValue(V value) {
			this.value = value;
			return this.value;
		}
		
		boolean isExpired(){
			return expireable && System.currentTimeMillis() - cacheTime > expireTime;
		}
	}
}
